package main

import (
	"github.com/globalsign/mgo/bson"
	"github.com/globalsign/mgo"
	"time"
)

//thanks https://mholt.github.io/json-to-go/
type GithubLimitErr struct {
	Message          string `json:"message"`
	DocumentationURL string `json:"documentation_url"`
}

type GithubRepo struct {
	ID              bson.ObjectId `bson:"_id" json:"_id"`
	Name            string        `bson:"name" json:"name,omitempty" valid:"required~first name is blank"` //repo name
	FullName        string        `bson:"full_name" json:"full_name"`
	HtmlUrl         string        `bson:"html_url" json:"html_url"`
	GitUrl          string        `bson:"git_url" json:"git_url"`
	SshUrl          string        `bson:"ssh_url" json:"ssh_url"`
	CloneUrl        string        `bson:"clone_url" json:"clone_url"`
	Description     string        `bson:"description" json:"description"`
	EditorComment   string        `bson:"editor_comment" json:"editor_comment"`
	DefaultBranch   string        `bson:"default_branch" json:"default_branch"`
	Language        string        `bson:"language" json:"language"`
	Size            int64         `bson:"size" json:"size"`
	StargazersCount int64         `bson:"stargazers_count" json:"stargazers_count"`
	WatchersCount   int64         `bson:"watchers_count" json:"watchers_count"`
	ForksCount      int64         `bson:"forks_count" json:"forks_count"`
	Archived        bool          `bson:"archived" json:"archived"`
	CreatedAt       time.Time     `bson:"created_at" json:"created_at"`
	UpdatedAt       time.Time     `bson:"updated_at" json:"updated_at"`
	PushedAt        time.Time     `bson:"pushed_at" json:"pushed_at"`
}

type GithubStarred struct {
	repos []GithubRepo
}

//Insert docs
func (db *StarDb) Insert(collection string, docs ...interface{}) error {
	s := db.Sess.Copy()
	defer s.Close()
	c := s.DB(db.Option.DbName).C(collection)
	err := c.Insert(docs...)
	return err
}

//FindByName find doc by name
func (db *StarDb) FindByName(collection string, name string) (*GithubRepo, error) {
	var restult GithubRepo
	s := db.Sess.Copy()
	defer s.Close()
	c := s.DB(db.Option.DbName).C(collection)
	err := c.Find(bson.M{"name": name}).One(&restult)
	return &restult, err
}

//FindByName find doc by url
func (db *StarDb) FindByFullName(collection string, fullName string) (*GithubRepo, error) {
	var restult GithubRepo
	s := db.Sess.Copy()
	defer s.Close()
	c := s.DB(db.Option.DbName).C(collection)
	err := c.Find(bson.M{"full_name": fullName}).One(&restult)
	return &restult, err
}

func (db *StarDb) RemoveByFullName(collection string, fullName string) (error) {
	s := db.Sess.Copy()
	defer s.Close()
	c := s.DB(db.Option.DbName).C(collection)
	err := c.Remove(bson.D{{Name: "full_name", Value: fullName}})
	if err != mgo.ErrNotFound {
		return err
	}
	return nil
}

func (db *StarDb) CountTotal(collection string) (int, error) {
	s := db.Sess.Copy()
	defer s.Close()
	c := s.DB(db.Option.DbName).C(collection)
	n, err := c.Count()
	return n, err
}

func (db *StarDb) FindByLang(collection, lang string, skip, limit int) (*[]GithubRepo, error) {
	var restult []GithubRepo
	s := db.Sess.Copy()
	defer s.Close()
	c := s.DB(db.Option.DbName).C(collection)
	err := c.Find(bson.M{"language": lang}).
		Sort("_id").
		Skip(skip).
		Limit(limit).
		All(&restult)
	return &restult, err
}

func (db *StarDb) Find(collection string, query interface{}, skip, limit int) (*[]GithubRepo, error) {
	var restult []GithubRepo
	s := db.Sess.Copy()
	defer s.Close()
	c := s.DB(db.Option.DbName).C(collection)
	err := c.Find(query).
		Sort("_id").
		Skip(skip).
		Limit(limit).
		All(&restult)
	return &restult, err
}

func (db *StarDb) CountArchived(collection string) (int, error) {
	s := db.Sess.Copy()
	defer s.Close()
	c := s.DB(db.Option.DbName).C(collection)
	n, err := c.Find(bson.M{"archived": true}).Count()
	return n, err
}
